#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""配置管理器模块"""

import os
import json
import logging
from datetime import datetime


class ConfigManager:
    """配置管理器类，负责应用程序的配置管理"""
    
    # 默认配置文件路径
    DEFAULT_CONFIG_FILE = os.path.join(os.path.expanduser("~"), ".kljmpythonied", "config.json")
    
    # 默认配置
    DEFAULT_CONFIG = {
        "editor": {
            "font": {
                "family": "Consolas",
                "size": 12,
                "weight": "normal"
            },
            "theme": "default",
            "tab_size": 4,
            "indent_size": 4,
            "use_spaces_for_tabs": True,
            "auto_indent": True,
            "line_numbers": True,
            "word_wrap": False,
            "highlight_current_line": True,
            "brace_matching": True,
            "code_folding": True,
            "show_whitespace": False
        },
        "designer": {
            "grid_size": 10,
            "show_grid": True,
            "snap_to_grid": True,
            "show_guides": True,
            "highlight_margin": 5,
            "default_font": {
                "family": "Arial",
                "size": 10
            }
        },
        "build": {
            "output_dir": "dist",
            "build_command": "python setup.py build",
            "run_command": "python {file}",
            "debug_command": "python -m debugpy --wait-for-client --listen 5678 {file}"
        },
        "ui": {
            "language": "zh_CN",
            "theme": "light",
            "toolbar_style": "icon_text_below",
            "status_bar": True,
            "welcome_screen": True,
            "recent_files_count": 10
        },
        "paths": {
            "projects": [],
            "templates": "",
            "resources": ""
        },
        "plugins": {
            "enabled": [],
            "disabled": [],
            "paths": []
        },
        "keyboard_shortcuts": {
            "new_file": "Ctrl+N",
            "open_file": "Ctrl+O",
            "save_file": "Ctrl+S",
            "save_file_as": "Ctrl+Shift+S",
            "close_file": "Ctrl+W",
            "undo": "Ctrl+Z",
            "redo": "Ctrl+Y",
            "cut": "Ctrl+X",
            "copy": "Ctrl+C",
            "paste": "Ctrl+V",
            "find": "Ctrl+F",
            "replace": "Ctrl+H",
            "run": "F5",
            "debug": "F9",
            "comment": "Ctrl+/",
            "uncomment": "Ctrl+Shift+/"
        }
    }
    
    def __init__(self, config_file=None):
        """初始化配置管理器
        
        Args:
            config_file: 配置文件路径，如果为None则使用默认路径
        """
        # 配置文件路径
        self.config_file = config_file or self.DEFAULT_CONFIG_FILE
        
        # 配置数据
        self.config = self.DEFAULT_CONFIG.copy()
        
        # 日志配置
        logging.basicConfig(
            level=logging.INFO,
            format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
        )
        self.logger = logging.getLogger("ConfigManager")
        
        # 加载配置
        self.load_config()
    
    def load_config(self):
        """加载配置文件
        
        Returns:
            bool: 是否加载成功
        """
        try:
            # 检查配置文件是否存在
            if not os.path.exists(self.config_file):
                # 创建配置目录
                config_dir = os.path.dirname(self.config_file)
                if config_dir and not os.path.exists(config_dir):
                    os.makedirs(config_dir)
                
                # 保存默认配置
                self.save_config()
                self.logger.info(f"配置文件不存在，已创建默认配置文件: {self.config_file}")
                return True
            
            # 读取配置文件
            with open(self.config_file, "r", encoding="utf-8") as f:
                loaded_config = json.load(f)
                
                # 合并配置（保留默认配置中不存在于加载配置中的项）
                self._merge_config(self.config, loaded_config)
                
            self.logger.info(f"配置文件加载成功: {self.config_file}")
            return True
        except json.JSONDecodeError as e:
            self.logger.error(f"配置文件格式错误: {str(e)}")
            # 使用默认配置
            self.config = self.DEFAULT_CONFIG.copy()
            self.save_config()
            return False
        except Exception as e:
            self.logger.error(f"加载配置文件失败: {str(e)}")
            return False
    
    def save_config(self):
        """保存配置文件
        
        Returns:
            bool: 是否保存成功
        """
        try:
            # 确保配置文件所在的目录存在
            config_dir = os.path.dirname(self.config_file)
            if config_dir and not os.path.exists(config_dir):
                os.makedirs(config_dir)
            
            # 保存配置文件
            with open(self.config_file, "w", encoding="utf-8") as f:
                json.dump(self.config, f, indent=4, ensure_ascii=False)
            
            self.logger.info(f"配置文件保存成功: {self.config_file}")
            return True
        except Exception as e:
            self.logger.error(f"保存配置文件失败: {str(e)}")
            return False
    
    def get(self, key, default=None):
        """获取配置项
        
        Args:
            key: 配置项键，可以是点分隔的路径（如 "editor.font.size"）
            default: 默认值
            
        Returns:
            配置项的值或默认值
        """
        # 分割键路径
        keys = key.split(".")
        
        # 遍历键路径获取配置值
        value = self.config
        for k in keys:
            if isinstance(value, dict) and k in value:
                value = value[k]
            else:
                return default
        
        return value
    
    def set(self, key, value):
        """设置配置项
        
        Args:
            key: 配置项键，可以是点分隔的路径（如 "editor.font.size"）
            value: 配置项的值
            
        Returns:
            bool: 是否设置成功
        """
        # 分割键路径
        keys = key.split(".")
        
        # 遍历键路径设置配置值
        config = self.config
        for i, k in enumerate(keys[:-1]):
            if k not in config or not isinstance(config[k], dict):
                config[k] = {}
            config = config[k]
        
        # 设置最终值
        config[keys[-1]] = value
        
        # 保存配置
        return self.save_config()
    
    def get_all(self):
        """获取所有配置
        
        Returns:
            dict: 所有配置
        """
        return self.config.copy()
    
    def set_all(self, config):
        """设置所有配置
        
        Args:
            config: 新的配置字典
            
        Returns:
            bool: 是否设置成功
        """
        if not isinstance(config, dict):
            self.logger.error("配置必须是字典类型")
            return False
        
        # 合并配置
        self._merge_config(self.config, config)
        
        # 保存配置
        return self.save_config()
    
    def reset_to_default(self, key=None):
        """重置配置到默认值
        
        Args:
            key: 配置项键，如果为None则重置所有配置
            
        Returns:
            bool: 是否重置成功
        """
        try:
            if key:
                # 分割键路径
                keys = key.split(".")
                
                # 找到默认配置中的对应值
                default_value = self.DEFAULT_CONFIG
                for k in keys:
                    if isinstance(default_value, dict) and k in default_value:
                        default_value = default_value[k]
                    else:
                        self.logger.warning(f"默认配置中不存在项: {key}")
                        return False
                
                # 设置为默认值
                return self.set(key, default_value)
            else:
                # 重置所有配置
                self.config = self.DEFAULT_CONFIG.copy()
                
                # 保存配置
                return self.save_config()
        except Exception as e:
            self.logger.error(f"重置配置失败: {str(e)}")
            return False
    
    def export_config(self, export_path):
        """导出配置
        
        Args:
            export_path: 导出路径
            
        Returns:
            bool: 是否导出成功
        """
        try:
            # 确保导出目录存在
            export_dir = os.path.dirname(export_path)
            if export_dir and not os.path.exists(export_dir):
                os.makedirs(export_dir)
            
            # 导出配置
            with open(export_path, "w", encoding="utf-8") as f:
                json.dump(self.config, f, indent=4, ensure_ascii=False)
            
            self.logger.info(f"配置导出成功: {export_path}")
            return True
        except Exception as e:
            self.logger.error(f"导出配置失败: {str(e)}")
            return False
    
    def import_config(self, import_path):
        """导入配置
        
        Args:
            import_path: 导入路径
            
        Returns:
            bool: 是否导入成功
        """
        try:
            # 检查导入文件是否存在
            if not os.path.exists(import_path):
                self.logger.error(f"导入文件不存在: {import_path}")
                return False
            
            # 读取导入文件
            with open(import_path, "r", encoding="utf-8") as f:
                imported_config = json.load(f)
                
            # 合并配置
            self._merge_config(self.config, imported_config)
            
            # 保存配置
            self.save_config()
            
            self.logger.info(f"配置导入成功: {import_path}")
            return True
        except json.JSONDecodeError as e:
            self.logger.error(f"导入文件格式错误: {str(e)}")
            return False
        except Exception as e:
            self.logger.error(f"导入配置失败: {str(e)}")
            return False
    
    def validate_config(self):
        """验证配置的有效性
        
        Returns:
            tuple: (是否有效, 错误消息)
        """
        try:
            # 检查编辑器配置
            editor_config = self.get("editor")
            if not isinstance(editor_config, dict):
                return False, "编辑器配置无效"
            
            # 检查字体配置
            font_config = editor_config.get("font", {})
            if not isinstance(font_config, dict):
                return False, "字体配置无效"
            
            # 检查字体大小
            font_size = font_config.get("size", 12)
            if not isinstance(font_size, int) or font_size <= 0:
                return False, "字体大小必须是正整数"
            
            # 检查标签大小
            tab_size = editor_config.get("tab_size", 4)
            if not isinstance(tab_size, int) or tab_size <= 0:
                return False, "标签大小必须是正整数"
            
            # 检查缩进大小
            indent_size = editor_config.get("indent_size", 4)
            if not isinstance(indent_size, int) or indent_size <= 0:
                return False, "缩进大小必须是正整数"
            
            # 检查构建配置
            build_config = self.get("build")
            if not isinstance(build_config, dict):
                return False, "构建配置无效"
            
            # 检查输出目录
            output_dir = build_config.get("output_dir", "dist")
            if not isinstance(output_dir, str) or not output_dir:
                return False, "输出目录无效"
            
            # 检查用户界面配置
            ui_config = self.get("ui")
            if not isinstance(ui_config, dict):
                return False, "用户界面配置无效"
            
            # 检查语言设置
            language = ui_config.get("language", "zh_CN")
            if not isinstance(language, str) or not language:
                return False, "语言设置无效"
            
            # 检查主题设置
            theme = ui_config.get("theme", "light")
            if not isinstance(theme, str) or theme not in ["light", "dark"]:
                return False, "主题设置无效"
            
            # 检查最近文件数量
            recent_files_count = ui_config.get("recent_files_count", 10)
            if not isinstance(recent_files_count, int) or recent_files_count < 0:
                return False, "最近文件数量必须是非负整数"
            
            # 配置有效
            return True, "配置有效"
        except Exception as e:
            self.logger.error(f"验证配置失败: {str(e)}")
            return False, f"验证配置失败: {str(e)}"
    
    def get_config_file_path(self):
        """获取配置文件路径
        
        Returns:
            str: 配置文件路径
        """
        return self.config_file
    
    def set_config_file_path(self, config_file):
        """设置配置文件路径
        
        Args:
            config_file: 新的配置文件路径
            
        Returns:
            bool: 是否设置成功
        """
        try:
            # 检查配置文件路径是否有效
            if not config_file:
                self.logger.error("配置文件路径不能为空")
                return False
            
            # 确保配置文件所在的目录存在
            config_dir = os.path.dirname(config_file)
            if config_dir and not os.path.exists(config_dir):
                os.makedirs(config_dir)
            
            # 更新配置文件路径
            self.config_file = config_file
            
            # 保存配置到新路径
            self.save_config()
            
            self.logger.info(f"配置文件路径已更改为: {config_file}")
            return True
        except Exception as e:
            self.logger.error(f"设置配置文件路径失败: {str(e)}")
            return False
    
    def _merge_config(self, original, updates):
        """合并配置字典
        
        Args:
            original: 原始配置字典
            updates: 要合并的配置字典
        """
        for key, value in updates.items():
            if isinstance(value, dict) and key in original and isinstance(original[key], dict):
                # 如果两者都是字典，递归合并
                self._merge_config(original[key], value)
            else:
                # 否则直接替换
                original[key] = value
    
    def update_recent_project(self, project_path):
        """更新最近使用的项目列表
        
        Args:
            project_path: 项目路径
        """
        try:
            # 获取当前最近项目列表
            recent_projects = self.get("paths.projects", [])
            
            # 如果项目已经在列表中，先移除
            if project_path in recent_projects:
                recent_projects.remove(project_path)
            
            # 添加到列表开头
            recent_projects.insert(0, project_path)
            
            # 限制列表长度
            max_count = self.get("ui.recent_files_count", 10)
            recent_projects = recent_projects[:max_count]
            
            # 更新配置
            self.set("paths.projects", recent_projects)
            
            return True
        except Exception as e:
            self.logger.error(f"更新最近项目失败: {str(e)}")
            return False
    
    def get_recent_projects(self):
        """获取最近使用的项目列表
        
        Returns:
            list: 最近使用的项目列表
        """
        # 获取最近项目列表
        recent_projects = self.get("paths.projects", [])
        
        # 过滤不存在的项目
        existing_projects = []
        for project_path in recent_projects:
            if os.path.exists(project_path):
                existing_projects.append(project_path)
        
        # 如果列表发生变化，更新配置
        if len(existing_projects) != len(recent_projects):
            self.set("paths.projects", existing_projects)
        
        return existing_projects
    
    def clear_recent_projects(self):
        """清除最近使用的项目列表
        
        Returns:
            bool: 是否清除成功
        """
        return self.set("paths.projects", [])